﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "GcmpDatabase.h"
#include "ClassId.h"
#include "NdbClassSchema.h"
#include "NdbClassSchemaLibrary.h"
#include "GbmpDefines.h"
#include "IUnserializationBehavior.h"
#include "GcmpApiDeclaration.h"
#include <vector>
#include <set>
#include <unordered_map>

#pragma warning (push)
#pragma warning (disable: 4251)

namespace gcmp
{
    /// \brief 类Schema管理器。对程序中所有的类schema进行管理
    class GCMP_DATABASE_EXPORT NdbClassSchemaLibraryOfCode : public NdbClassSchemaLibrary
    {
        DEFINE_CAST_DERIVED(gcmp::NdbClassSchemaLibraryOfCode, gcmp::NdbClassSchemaLibrary)
        CANNOT_COPY_OR_ASSIGN(NdbClassSchemaLibraryOfCode)
    public:
        ~NdbClassSchemaLibraryOfCode(void);

    public:
        static NdbClassSchemaLibraryOfCode* GetInstance();

        NdbClassSchema* CreateClassSchema(
            const ClassId & parentClassId,
            const ClassId & classId,
            const std::wstring & parentClassName,
            const std::wstring & className,
            CreateNdbObjectFunction createFunction,
            const Guid & assemblyId,
            const std::wstring & assemblyName,
            UInt64 size
        );

        std::vector<const NdbClassSchema*> GetClassSchemas() const;

        void Dump();

        /// \brief 导出类Schema管理器中ClassSchema的信息到指定XML文件
        ///
        /// 导出信息包括ClassSchema的classId,模块名，版本及类名以及其父类的classId及类名，还有其属性信息（属性名称及类型）
        /// \param filePath 保存的文件路径，文件扩展名必须为xml格式
        /// \param[out] pErrorMessage 如果传入非空，Dump失败时返回错误信息
        /// \return bool 成功返回true;失败false
        bool ExportClassSchemasAsXmlFile(const std::wstring& filePath, std::wstring* pErrorMessage = nullptr);

        bool CheckClassSchema() const;

        void Serialize(IIOStream & ioStream) const;

        SchemaError UnserializeToLibrary(IIOStream& ioStream, NdbClassSchemaLibrary * pSchemaLibrary);

        void UpdateClassVersion(const ClassId & classId, UInt32 version);

        /// \brief 设置ClassSchema的状态
        ///
        /// \param classId ClassSchema对应的classId。
        /// \param isClassSchemaExist ClassSchema的状态，true表示ClassSchema存在，false表示ClassSchema不存在，已被删除。
        /// \return void
        void SetIsClassSchemaExist(const ClassId & classId, bool isClassSchemaExist);

        /// \brief 获取ClassSchema的状态
        ///
        /// \param classId ClassSchema对应的classId。
        /// \return bool true表示ClassSchema存在，false表示ClassSchema不存在，已被删除。
        bool IsClassSchemaExist(const ClassId & classId) const;

        void RegisterUnserializationBehavior(const Guid & guid, IUnserializationBehavior * pBehavior);

        IUnserializationBehavior * GetUnserializationBehavior(const Guid & guid);
        // 父类NdbClassSchemaLibrary纯虚函数实现
    public:
        virtual UInt32 GetClassSchemaCount() const override { return (UInt32)m_classSchemaArr.size(); }

        virtual UInt32 GetMajorVersion() const override;

        virtual NdbClassSchema * AddClassSchema(gcmp::OwnerPtr<NdbClassSchema> opClassSchema) override;

        virtual bool GetClassIdByIndex(UInt32 index, ClassId & classId) const override;

        virtual const NdbClassSchema* GetSchemaByClassId(const ClassId & classId) const override;

        virtual bool BuildClassHierarchy() override;

        virtual bool IncreaseBuildClassHierarchy(NdbClassSchema * pBuildingClassSchema) override;

        virtual std::wstring GetName() const override { return L"ClassSchemaLibraryOfCode"; }

        const std::wstring& GetUnserializeErrorMessage() const { return m_unserializeErrorMessage; }

        void ClearUnserializeErrorMessage() { m_unserializeErrorMessage.clear(); }
    public:
        NdbClassSchema* GetSchemaByClassIDFW(const ClassId & classId);

        std::vector<const NdbClassSchema*> GetInstanceCanBeSavedClassSchemas() const;

    private:
        friend class NdbClassSchemaLibraryOfFile;
        friend class NdbFileManager;

        NdbClassSchemaLibraryOfCode(void);

        std::vector<OwnerPtr<NdbClassSchema>> m_classSchemaArr;
        std::unordered_map<ClassId, UInt32, ClassIdHasher> m_classId2Index;
        std::unordered_map<ClassId, UInt32, ClassIdHasher> m_classVersions;
        std::unordered_map<ClassId, bool, ClassIdHasher> m_classStateMap;
        std::unordered_map<Guid, IUnserializationBehavior*, GuidHasher> m_unSerializationBehaviors;
        std::wstring m_unserializeErrorMessage;
    };
}

#pragma warning (pop)

